package com.blue.controller.author;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.blue.common.annotation.IgnoreToken;
import com.blue.common.annotation.NotNull;
import com.blue.common.constant.CommonConstant;
import com.blue.common.entity.ResponseResult;
import com.blue.common.exception.CustomException;
import com.blue.common.utils.AESUtils;
import com.blue.common.utils.ConvertUtils;
import com.blue.dto.author.UserDTO;
import com.blue.po.author.UserPO;
import com.blue.service.author.ILoginService;
import com.blue.service.author.IUserService;
import com.blue.service.system.ILoginInfoService;
import com.blue.vo.author.UserVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/author")
@Tag(name = "系统登录确权")
public class LoginController {

    @Autowired
    private ILoginService loginService;

    @Autowired
    private IUserService userService;

    @Autowired
    private ILoginInfoService loginInfoService;

    @GetMapping("/captchaImage")
    @Operation(summary = "生成验证码")
    @IgnoreToken
    public ResponseResult<?> captchaImage() {
        Map<String, Object> map = loginService.captchaImage();
        return ResponseResult.okResult(map);
    }

    @PostMapping("/login")
    @Operation(summary = "系统登录")
    @NotNull(value = "userNo", message = "账号不能为空")
    @NotNull(value = "password", message = "密码不能为空")
    @NotNull(value = "key", message = "验证码秘钥不能为空")
    @NotNull(value = "captcha", message = "验证码不能为空")
    @IgnoreToken
    public ResponseResult<?> login(@RequestBody UserDTO requestDTO, HttpServletRequest request, HttpServletResponse response) throws Exception {
        //异步线程请求会被回收
        AsyncContext asyncContext = request.startAsync(request, response);
        try {
            UserVO userVO = loginService.login(requestDTO, request);
            return ResponseResult.okResult(userVO);
        } catch (Exception e) {
            requestDTO.setStatus(e.getMessage());
            throw new CustomException(e.getMessage());
        } finally {
            loginInfoService.recordLoginInfo(requestDTO, request, asyncContext);
        }
    }

    @PostMapping("/token")
    @Operation(summary = "获取Token")
    @NotNull(value = "userNo", message = "账号不能为空")
    @NotNull(value = "password", message = "密码不能为空")
    @IgnoreToken
    public ResponseResult<?> getToken(@RequestBody UserDTO requestDTO, HttpServletRequest request) throws Exception {
        UserVO userVO = loginService.getToken(requestDTO, request);
        return ResponseResult.okResult(userVO);
    }

    @PostMapping("/verifyPassword")
    @Operation(summary = "密码校验")
    @NotNull(value = "userId", message = "用户ID不能为空")
    @NotNull(value = "password", message = "密码不能为空")
    public ResponseResult<?> verifyPassword(@RequestBody UserDTO requestDTO) throws Exception {
        String passWord = AESUtils.encrypt(requestDTO.getPassword());
        UserPO userPO = userService.getOne(new LambdaQueryWrapper<UserPO>()
                .eq(UserPO::getUserId, requestDTO.getUserId())
                .eq(UserPO::getPassword, passWord)
                .eq(UserPO::getStatus, CommonConstant.NORMAL));
        if (userPO != null) {
            return ResponseResult.okResult();
        }
        return ResponseResult.errorResult("旧密码验证错误");
    }

    @PostMapping("/editPassword")
    @Operation(summary = "修改密码")
    @NotNull(value = "userId", message = "用户ID不能为空")
    @NotNull(value = "password", message = "密码不能为空")
    public ResponseResult<?> editPassword(@RequestBody UserDTO requestDTO) throws Exception {
        UserPO userPO = ConvertUtils.convert(UserPO.class, requestDTO);
        String password = AESUtils.encrypt(requestDTO.getPassword());
        userPO.setPassword(password);
        userService.updateById(userPO);
        return ResponseResult.okResult();
    }
}
